package de.gameduell.framework.game.card {

	import de.gameduell.framework.gui.wrapper.SpriteWrapper;
	import de.gameduell.framework.util.Library;

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;

	/**
	 * @author cbra
	 */
	public class Card extends SpriteWrapper {
		
		public static const BLOCKED_CARD_CLICK:String = "BLOCKED_CARD_CLICK";
		
		private var card_prefix:String = "card_";
		protected var _coverClip:Sprite;
		protected var _highlightClip:Sprite;
		protected var _cardClip:Sprite;
		private var _symbol:int = 13;
		private var _family:int;
		private var _colour:int;
		private var _stack:CardStack;
		private var _index:int;
		private var _cardString:String;
		private var _blockReason:String = null;
		protected var _active:Boolean;

		/**  
		 * @param aCard      = second part of the Name of the cardlip to load
		 * @param aCover     = Name of the CoverClip of the Card
		 * @param aHighlight = Name of the Highlight for the Card
		 * @param alternativeCardPrefix = alternative second part for the cardclipname
		**/
		public function Card(aCard:String, aCover:String = "", aHighlight:String = "", alternativeCardPrefix:String = "card_") {
			super(new Sprite());
			card_prefix = alternativeCardPrefix == card_prefix?card_prefix:alternativeCardPrefix;
			createCard(aCard, aCover, aHighlight);
			
			addChild(_cardClip);
			if(aHighlight.length > 0) {
				addChild(_highlightClip);
				_highlightClip.visible = false;
			}
			if(aCover.length > 0) {
				addChild(_coverClip);
				_coverClip.visible = false;
			}
			active = true;
		}
		
		/**  
		 * @return _blockReason = getter for the reason why a card is blocked
		**/	
		public function get blockReason():String {
			return _blockReason;
		}
		
		/**  
		 * @param aReason     = reason why a card is blocked
		 * @param redOffset   = red color to be darkened
		 * @param greenOffset = green color to be darkened
		 * @param blueOffset  = blue color to be darkened
		**/
		public function block(aReason:String = null, redOffset:int = -50, greenOffset:int = -50, blueOffset:int = -50):void {
			_blockReason = aReason;
			var darker:ColorTransform = new ColorTransform(1, 1, 1, 1, redOffset, greenOffset, blueOffset);
			_sprite.transform.colorTransform = darker;
			active = false;
			addEventListener(MouseEvent.MOUSE_DOWN, onIllegalCardEvent);
		}

		private function onIllegalCardEvent(event:MouseEvent):void {
			dispatchEvent(new CardEvent(this, BLOCKED_CARD_CLICK));
		}
		
		/**  
		 * activate the card and remove the dark color
		**/	
		public function unBlock():void {
			_blockReason = null;
			removeEventListener(MouseEvent.MOUSE_DOWN, onIllegalCardEvent);
			_sprite.transform.colorTransform = new ColorTransform();
			active = true;
		}
		
		/**  
		 * @param isActive = activate or deactivate the card 
		**/	
		public function set active(isActive:Boolean):void {
			_active = isActive;
			
			if(isActive) {
				addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
				addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
				addEventListener(MouseEvent.MOUSE_DOWN, onCardEvent);
				addEventListener(MouseEvent.MOUSE_UP, onCardEvent);
				addEventListener(MouseEvent.CLICK, onCardEvent);
			}else {
				removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
				removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
				removeEventListener(MouseEvent.MOUSE_DOWN, onCardEvent);
				removeEventListener(MouseEvent.MOUSE_UP, onCardEvent);
				removeEventListener(MouseEvent.CLICK, onCardEvent);

				_highlightClip.visible = false;
			}
		}

		/**
		 * is active? 
		 */
		public function get active():Boolean{
			return _active;
		}
		
		/**
		 * onMouseOver, sets highlight
		 * @param event
		 */
		public function onMouseOver(event:Event):void {
			if(_highlightClip != null) {
				_highlightClip.visible = true;
			}
		}

		/**
		 * onMouseOver, hide highlight
		 * @param event
		 */
		public function onMouseOut(event:Event):void {
			if(_highlightClip != null) {
				_highlightClip.visible = false;
			}
		}

		/**
		 * onMouseClick, throw a card-event
		 * @param event
		 */
		public function onCardEvent(event:Event):void {
			switch(event.type){
				case(MouseEvent.CLICK): 
					dispatchEvent(new CardEvent(this, CardEvent.CLICK));
					break;
				case(MouseEvent.MOUSE_DOWN): 
					dispatchEvent(new CardEvent(this, CardEvent.MOUSE_DOWN));
					break;
				case(MouseEvent.MOUSE_UP): 
					dispatchEvent(new CardEvent(this, CardEvent.MOUSE_UP));
					break;
			}	
		}

		private function createCard(aCard:String, aCover:String, aHighlight:String):void {
			var library:Library = Library.getInstance();
			_cardString = aCard;
			_cardClip   = library.createSprite(card_prefix + aCard);
			if(aCover.length > 0) {
				_coverClip = library.createSprite(aCover);
			}
			if(aHighlight.length > 0) {
				_highlightClip = library.createSprite(aHighlight);
			}
		}

		/**
		 * @param clip the new cover clip (card backside)
		 */
		public function set coverClip( clip:Sprite ):void {
			_coverClip = clip;
			addChild(_coverClip);
		}
		
		/**
		 * @param clip the new cover clip (card backside)
		 */
		public function set cardClip( clip:Sprite ):void {
			_cardClip = clip;
			addChild(_cardClip);
		}

		/**
		 * @param clip the new highlight clip (card highlight)
		 */
		public function set highlight( isHighlighted:Boolean ):void {
			if(_highlightClip != null) {
				_highlightClip.visible = isHighlighted;
			}
		}

		/**
		 * @param clip the new highlight clip (card highlight)
		 */
		public function set flip( isFlipped:Boolean ):void {
			if(_coverClip != null){
				_coverClip.visible = isFlipped;
			}
		}

		/**
		 * @param newSymbol the symbol (like king, jack or queen)
		 */
		public function set symbol(newSymbol:int):void {
			_symbol = newSymbol;
		}

		/**
		 * @param newFamily the family (like diamonds)
		 */
		public function set family(newFamily:int):void {
			_family = newFamily;
		}

		/**
		 * @param newColour the colour (like red or black)
		 */
		public function set colour(newColour:int):void {
			_colour = newColour;
		}

		/**
		 * @param newIndex the index in the stack
		 */
		public function set index(newIndex:int):void {
			_index = newIndex;
		}

		/**
		 * @param the stack the card is part of
		 */
		public function set stack(aStack:CardStack):void {
			_stack = aStack;
		}

		/**
		 * @return the stack the card is part of
		 */
		public function get stack():CardStack {
			return _stack;
		}
		
		/**
		 * @return the identifier of the card
		 */
		public function set cardString(aCard:String):void {
			_cardString = aCard;
		}

		/**
		 * @return the symbol of the card
		 */
		public function get symbol():int {
			return _symbol;
		}

		/**
		 * @return the family of the card
		 */
		public function get family():int {
			return _family;
		}

		/**
		 * @return the type of the card
		 */
		public function get colour():int {
			return _colour;
		}

		/**
		 * @return the index of the card in the stack
		 */
		public function get index():int {
			return _index;
		}

		/**
		 * @return boolean 	returns true when coverClip is visible
		 */
		public function get flip():Boolean {
			return _coverClip.visible;
		}

		/**
		 * @return boolean 	returns true is highlightClip is visible
		 */
		public function get highlight():Boolean {
			return _highlightClip.visible;
		}
		
		/**
		 * @return String 	returns the identifier of the card
		 */
		public function get cardString():String {
			return _cardString;
		}
		
		/**
		 * @return the clip of the card
		 */
		public function get cardClip():Sprite{
			return _cardClip;
		}
		
		/**
		 * @return clip the new cover clip (card backside)
		 */
		public function get coverClip():Sprite{
			return _coverClip;
		}
		
		/**
		 * @return the highlight clip (card highlight)
		 */
		public function get highlightClip():Sprite{
			return _highlightClip;
		}

		/*###################################################
		#		   				MISC						#
		#####################################################*/
	
		/**
		 * flip card's moveclip according to current state
		 */	
		public function toggleFlip():void {
			_coverClip.visible = !_coverClip.visible ;
		}
		
		/**
		 * change card's highlight according to current state
		 */	
		public function toggleHighlight():void {
			_highlightClip.visible = !_highlightClip.visible;
		}
		
		/**
		 * @param factor scale card to factor
		 */	
		public function scaleCard(factor:Number):void {
			scale = factor;
		}
		
		/**
		 * @param set the factor the card is scaled to
		 */
		public function set scale(factor:Number):void {
			_cardClip.scaleX = factor ;
			_cardClip.scaleY = factor ;
			if(_coverClip != null) {
				_coverClip.scaleX = factor ;
				_coverClip.scaleY = factor ;
			}
			if(_highlightClip != null) {
				_highlightClip.scaleX = factor ;
				_highlightClip.scaleY = factor ;
			}
		}
	}
}
